package com.spukmk3me.impl.libgdx;

import java.util.LinkedList;
import java.util.Queue;

import com.spukmk3me.io.userinput.ButtonEvent;
import com.spukmk3me.io.userinput.ButtonInput;
import com.spukmk3me.io.userinput.InputSystem;
import com.spukmk3me.io.userinput.PointerEvent;
import com.spukmk3me.io.userinput.PointerInput;

import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;

public class LibgdxInputSystem implements InputSystem, InputProcessor
{
    public LibgdxInputSystem()
    {
        m_buttonEvents = new LinkedList<ButtonEvent>();
        m_pointerEvents = new LinkedList<PointerEvent>();
        m_pointerInput = new PointerInput( 1 );
        m_buttonInput = new LibgdxButtonInput();
        initializeKeyMap();
    }

    @Override
    public boolean keyDown( int keycode )
    {
        m_buttonEvents.add( new ButtonEvent( fromGdxKey( keycode ), (char)0, ButtonEvent.PRESS ) );
        m_buttonInput.keyDown( keycode );
        return true;
    }

    @Override
    public boolean keyUp( int keycode )
    {
        m_buttonEvents.add( new ButtonEvent( fromGdxKey( keycode ), (char)0, ButtonEvent.RELEASE ) );
        m_buttonInput.keyUp( keycode );
        return true;
    }

    @Override
    public boolean keyTyped( char character )
    {
        m_buttonEvents.add( new ButtonEvent( ButtonEvent.KEY_NONE, character, ButtonEvent.TYPE ) );
        m_buttonInput.keyTyped( character );
        return true;
    }

    @Override
    public boolean touchDown( int x, int y, int pointer, int button )
    {
        m_pointerInput.pointerDown( x, y, 0 );
        m_pointerEvents.add( new PointerEvent( pointer, x, y, PointerEvent.PRESS ) );
        return true;
    }

    @Override
    public boolean touchUp( int x, int y, int pointer, int button )
    {
        m_pointerInput.pointerUp( x, y, 0 );
        m_pointerEvents.add( new PointerEvent( button, x, y, PointerEvent.RELEASE ) );
        return true;
    }

    @Override
    public boolean touchDragged( int x, int y, int pointer )
    {
        m_pointerInput.pointerDragged( x, y );
        m_pointerEvents.add( new PointerEvent( pointer, x, y, PointerEvent.DRAG ) );
        return true;
    }

    @Override
    public boolean mouseMoved( int x, int y )
    {
        //m_pointerEvents.add( new PointerEvent( pointer, x, y, PointerEvent.DRAG ) );
        return false;
    }

    @Override
    public boolean scrolled( int amount )
    {
        return false;
    }

    @Override
    public ButtonEvent getNextButtonEvent()
    {
        if ( m_buttonEvents.isEmpty() )
            return null;
        
        return m_buttonEvents.remove();
    }

    @Override
    public void clearButtonEvents()
    {
        m_buttonEvents.clear();
    }

    @Override
    public PointerEvent getNextPointerEvent()
    {
        if ( m_pointerEvents.isEmpty() )
            return null;
        
        return m_pointerEvents.remove();
    }

    @Override
    public void clearPointerEvents()
    {
        m_pointerEvents.clear();
    }
    
    private static int fromGdxKey( int gdxKey )
    {
        if ( gdxKey == Keys.ANY_KEY )
            return ButtonEvent.KEY_NONE;
        
        return gtnMap[ gdxKey ];
    }
    
    private static void initializeKeyMap()
    {
        gtnMap = new int[ 256 ];
        gtnMap[ Keys.NUM_0 ] = ButtonEvent.KEY_0;
        gtnMap[ Keys.NUM_1 ] = ButtonEvent.KEY_1;
        gtnMap[ Keys.NUM_2 ] = ButtonEvent.KEY_2;
        gtnMap[ Keys.NUM_3 ] = ButtonEvent.KEY_3;
        gtnMap[ Keys.NUM_4 ] = ButtonEvent.KEY_4;
        gtnMap[ Keys.NUM_5 ] = ButtonEvent.KEY_5;
        gtnMap[ Keys.NUM_6 ] = ButtonEvent.KEY_6;
        gtnMap[ Keys.NUM_7 ] = ButtonEvent.KEY_7;
        gtnMap[ Keys.NUM_8 ] = ButtonEvent.KEY_8;
        gtnMap[ Keys.NUM_9 ] = ButtonEvent.KEY_9;
        
        gtnMap[ Keys.A ] = ButtonEvent.KEY_A;
        gtnMap[ Keys.B ] = ButtonEvent.KEY_B;
        gtnMap[ Keys.C ] = ButtonEvent.KEY_C;
        gtnMap[ Keys.D ] = ButtonEvent.KEY_D;
        gtnMap[ Keys.E ] = ButtonEvent.KEY_E;
        gtnMap[ Keys.F ] = ButtonEvent.KEY_F;
        gtnMap[ Keys.G ] = ButtonEvent.KEY_G;
        gtnMap[ Keys.H ] = ButtonEvent.KEY_H;
        gtnMap[ Keys.I ] = ButtonEvent.KEY_I;
        gtnMap[ Keys.J ] = ButtonEvent.KEY_J;
        gtnMap[ Keys.K ] = ButtonEvent.KEY_K;
        gtnMap[ Keys.L ] = ButtonEvent.KEY_L;
        gtnMap[ Keys.M ] = ButtonEvent.KEY_M;
        gtnMap[ Keys.N ] = ButtonEvent.KEY_N;
        gtnMap[ Keys.O ] = ButtonEvent.KEY_O;
        gtnMap[ Keys.P ] = ButtonEvent.KEY_P;
        gtnMap[ Keys.Q ] = ButtonEvent.KEY_Q;
        gtnMap[ Keys.R ] = ButtonEvent.KEY_R;
        gtnMap[ Keys.S ] = ButtonEvent.KEY_S;
        gtnMap[ Keys.T ] = ButtonEvent.KEY_T;
        gtnMap[ Keys.U ] = ButtonEvent.KEY_U;
        gtnMap[ Keys.V ] = ButtonEvent.KEY_V;
        gtnMap[ Keys.W ] = ButtonEvent.KEY_W;
        gtnMap[ Keys.X ] = ButtonEvent.KEY_X;
        gtnMap[ Keys.Y ] = ButtonEvent.KEY_Y;
        gtnMap[ Keys.Z ] = ButtonEvent.KEY_Z;
        
        gtnMap[ Keys.ALT_LEFT ] = ButtonEvent.KEY_LMENU;
        gtnMap[ Keys.ALT_RIGHT ] = ButtonEvent.KEY_RMENU;
        gtnMap[ Keys.APOSTROPHE ] = ButtonEvent.KEY_APOSTROPHE;
        gtnMap[ Keys.AT ] = ButtonEvent.KEY_AT;
        gtnMap[ Keys.BACK ] = ButtonEvent.KEY_BACK;
        gtnMap[ Keys.BACKSLASH ] = ButtonEvent.KEY_BACKSLASH;
        gtnMap[ Keys.CALL ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.CAMERA ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.CLEAR ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.COMMA ] = ButtonEvent.KEY_COMMA;
        
        gtnMap[ Keys.DEL ] = ButtonEvent.KEY_DELETE;
        gtnMap[ Keys.BACKSPACE ] = ButtonEvent.KEY_BACK;
        gtnMap[ Keys.FORWARD_DEL ] = ButtonEvent.KEY_NONE;
        
        gtnMap[ Keys.DPAD_CENTER ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.DPAD_UP ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.DPAD_DOWN ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.DPAD_LEFT ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.DPAD_RIGHT ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.CENTER ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.UP ] = ButtonEvent.KEY_UP;
        gtnMap[ Keys.DOWN ] = ButtonEvent.KEY_DOWN;
        gtnMap[ Keys.LEFT ] = ButtonEvent.KEY_LEFT;
        gtnMap[ Keys.RIGHT ] = ButtonEvent.KEY_RIGHT;
        
        gtnMap[ Keys.ENDCALL ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.ENTER ] = ButtonEvent.KEY_RETURN;
        gtnMap[ Keys.ENVELOPE ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.EQUALS ] = ButtonEvent.KEY_EQUALS;
        gtnMap[ Keys.EXPLORER ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.FOCUS ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.GRAVE ] = ButtonEvent.KEY_GRAVE;
        gtnMap[ Keys.HEADSETHOOK ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.HOME ] = ButtonEvent.KEY_HOME;
        gtnMap[ Keys.LEFT_BRACKET ] = ButtonEvent.KEY_LBRACKET;
        
        gtnMap[ Keys.MEDIA_FAST_FORWARD ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.MEDIA_NEXT ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.MEDIA_PLAY_PAUSE ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.MEDIA_PREVIOUS ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.MEDIA_REWIND ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.MEDIA_STOP ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.MENU ] = ButtonEvent.KEY_NONE;
        
        gtnMap[ Keys.MINUS ] = ButtonEvent.KEY_MINUS;
        gtnMap[ Keys.MUTE ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.NOTIFICATION ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.NUM ] = ButtonEvent.KEY_NUMLOCK;
        gtnMap[ Keys.PERIOD ] = ButtonEvent.KEY_PERIOD;
        gtnMap[ Keys.PLUS ] = ButtonEvent.KEY_ADD;
        gtnMap[ Keys.POUND ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.POWER ] = ButtonEvent.KEY_POWER;
        gtnMap[ Keys.RIGHT_BRACKET ] = ButtonEvent.KEY_RBRACKET;
        gtnMap[ Keys.SEARCH ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.SEMICOLON ] = ButtonEvent.KEY_SEMICOLON;
        gtnMap[ Keys.SHIFT_LEFT ] = ButtonEvent.KEY_LSHIFT;
        gtnMap[ Keys.SHIFT_RIGHT ] = ButtonEvent.KEY_RSHIFT;
        gtnMap[ Keys.SLASH ] = ButtonEvent.KEY_SLASH;
        gtnMap[ Keys.SOFT_LEFT ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.SOFT_RIGHT ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.SPACE ] = ButtonEvent.KEY_SPACE;
        gtnMap[ Keys.STAR ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.SYM ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.TAB ] = ButtonEvent.KEY_TAB;
        gtnMap[ Keys.UNKNOWN ] = ButtonEvent.KEY_UNLABELED;
        gtnMap[ Keys.VOLUME_UP ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.VOLUME_DOWN ] = ButtonEvent.KEY_NONE;
        
        
        gtnMap[ Keys.CONTROL_LEFT ] = ButtonEvent.KEY_LCONTROL;
        gtnMap[ Keys.CONTROL_RIGHT ] = ButtonEvent.KEY_RCONTROL;
        gtnMap[ Keys.ESCAPE ] = ButtonEvent.KEY_ESCAPE;
        gtnMap[ Keys.END ] = ButtonEvent.KEY_END;
        gtnMap[ Keys.INSERT ] = ButtonEvent.KEY_INSERT;
        gtnMap[ Keys.PAGE_UP ] = ButtonEvent.KEY_PRIOR;
        gtnMap[ Keys.PAGE_DOWN ] = ButtonEvent.KEY_NEXT;
        
        gtnMap[ Keys.PICTSYMBOLS ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.SWITCH_CHARSET ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_CIRCLE ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_A ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_B ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_C ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_X ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_Y ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_Z ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_L1 ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_R1 ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_L2 ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_R2 ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_THUMBL ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_THUMBR ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_START ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_SELECT ] = ButtonEvent.KEY_NONE;
        gtnMap[ Keys.BUTTON_MODE ] = ButtonEvent.KEY_NONE;
        
        gtnMap[ Keys.COLON ] = ButtonEvent.KEY_COLON;
        gtnMap[ Keys.F1 ] = ButtonEvent.KEY_F1;
        gtnMap[ Keys.F2 ] = ButtonEvent.KEY_F2;
        gtnMap[ Keys.F3 ] = ButtonEvent.KEY_F3;
        gtnMap[ Keys.F4 ] = ButtonEvent.KEY_F4;
        gtnMap[ Keys.F5 ] = ButtonEvent.KEY_F5;
        gtnMap[ Keys.F6 ] = ButtonEvent.KEY_F6;
        gtnMap[ Keys.F7 ] = ButtonEvent.KEY_F7;
        gtnMap[ Keys.F8 ] = ButtonEvent.KEY_F8;
        gtnMap[ Keys.F9 ] = ButtonEvent.KEY_F9;
        gtnMap[ Keys.F10 ] = ButtonEvent.KEY_F10;
        gtnMap[ Keys.F11 ] = ButtonEvent.KEY_F11;
        gtnMap[ Keys.F12 ] = ButtonEvent.KEY_F12;
    }
    
    public PointerInput getPointerInput()
    {
        return m_pointerInput;
    }
    
    public ButtonInput getButtonInput()
    {
        return m_buttonInput;
    }
    
    private static int[] gtnMap;
    
    private Queue<ButtonEvent>  m_buttonEvents;
    private Queue<PointerEvent> m_pointerEvents;
    private PointerInput        m_pointerInput;
    private LibgdxButtonInput   m_buttonInput;
}
